package com.gopay.common.cps.service.autosettle.impl;

import com.gopay.common.constants.autosettle.SettlementExchangeConstants;
import com.gopay.common.constants.autosettle.WorkDayEnum;
import com.gopay.common.constants.bank.BankConstants;
import com.gopay.common.constants.batch.BatchPayConstants;
import com.gopay.common.domain.cps.CpsGenMainOrder;
import com.gopay.common.domain.cps.CpsGenPayOrder;
import com.gopay.common.order.dao.CommonQueryDAO;
import com.gopay.common.user.dao.CloudCustAcctRelDao;
import com.gopay.common.util.StringTools;
import org.apache.commons.lang3.StringUtils;
import org.apache.log4j.Logger;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.*;

//import com.gopay.common.util.DateUtils;

/**
 * @author lianpeng
 *	新自动结算辅助类
 */
@Service(value = "autoSettleBankCodeAdapter")
public class AutoSettleBankCodeAdapter {
	
	protected Logger logger = Logger.getLogger(getClass());
    @Resource(name = "commonQueryDAO")
    private CommonQueryDAO commonQueryDAO;
    
    @Resource(name = "autoSettleHelper")
    private AutoSettleHelper autoSettleHelper;
    
    @Resource(name = "cloudCustAcctRelDao")
	private CloudCustAcctRelDao cloudCustAcctRelDao;
    
    /**
     * @param mainOrder
     * @param bankName
     * @param bcFlag
     * @param cardNum
     * @param bankCode AutoSettleBankCodeAdapter.queryPayBankCode的处理结果
     * @return
     */
    public String convertSettlementExchange(CpsGenMainOrder mainOrder, String bankName, String bcFlag, String cardNum, String bankCode, String splitFlag){
    	if(bankName==null){
    		logger.error("gopayOrderId_" + mainOrder.getGopayOrderId()+" bankName is null");
    		return null;
    	}
    	if(BankConstants.BANK_LOGO_CMB.equals(bankCode)){
    		if (autoSettleHelper.isPrivate(bcFlag)) {
    			return SettlementExchangeConstants.STLM_EX_CMB_P;
    		}
    		return SettlementExchangeConstants.STLM_EX_CMB_C;
    	}
    	if(BankConstants.BANK_LOGO_ABC.equals(bankCode)){
    		return SettlementExchangeConstants.STLM_EX_ABC;
    	}
    	
    	if(BankConstants.BANK_LOGO_BOC.equals(bankCode)){
    		return SettlementExchangeConstants.STLM_EX_BOC;
    	}
    	
    	if(BankConstants.BANK_LOGO_CCB.equals(bankCode)){
    		return SettlementExchangeConstants.STLM_EX_CCB;
    	}
    	
    	if (BankConstants.BANK_LOGO_ICBC.equals(bankCode)) {
			if (bankName.indexOf("工行") != -1 || bankName.indexOf("工商") != -1) {
				return SettlementExchangeConstants.STLM_EX_ICBC;
			} else if (!autoSettleHelper.isPrivate(bcFlag) && useCross(mainOrder, bankName, bcFlag, cardNum)) {
				// 对公转账走工行大额
				return SettlementExchangeConstants.STLM_EX_ICBC_CROSS;
			} else if (autoSettleHelper.isPrivate(bcFlag) && autoSettleHelper.isPettyAmt(mainOrder.getMerTxnAmt()) && !StringUtils.equals(splitFlag, BatchPayConstants.SPLIT_FLAG_YES)
					&& useSuper(mainOrder, bankName, bcFlag, cardNum)) {
				// 对私小于等于5万并且非拆单走工行超级网银
				return SettlementExchangeConstants.STLM_EX_ICBC_SUPER;
			} else if (autoSettleHelper.isPrivate(bcFlag) && !autoSettleHelper.isPettyAmt(mainOrder.getMerTxnAmt()) && useCross(mainOrder, bankName, bcFlag, cardNum)) {
				// 对私大于5W的走大额
				return SettlementExchangeConstants.STLM_EX_ICBC_CROSS;
			} else if (StringUtils.equals(splitFlag, BatchPayConstants.SPLIT_FLAG_YES) && useCross(mainOrder, bankName, bcFlag, cardNum)) {
				// 对私小于等于5W并且拆单的走工行大额
				return SettlementExchangeConstants.STLM_EX_ICBC_CROSS;
			} 
		}
    	
    	return null;
    }
    
    private String queryPayBankCode(CpsGenMainOrder mainOrder,String bankName,String bcFlag,String cardNum, String custId, String acctId, String banks,String splitFlag){
    	String result = null;
    	if(bankName==null){
    		logger.error("gopayOrderId_" + mainOrder.getGopayOrderId()+" bankName is null");
    		return null;
    	}
    	
    	logger.error("gopayOrderId_" + mainOrder.getGopayOrderId()+" bankName is "+ bankName);
    	if(bankName.indexOf("工行")!=-1 || bankName.indexOf("工商")!=-1){
    		result = BankConstants.BANK_LOGO_ICBC;
    	}else if(bankName.indexOf("招行")!=-1 || bankName.indexOf("招商")!=-1){
    		result = BankConstants.BANK_LOGO_CMB;
    	}else if(bankName.indexOf("农行")!=-1 || bankName.indexOf("农业银行")!=-1){
    		result = BankConstants.BANK_LOGO_ABC;
    	}else if(bankName.indexOf("中行")!=-1 || bankName.indexOf("中国银行")!=-1){
    		result = BankConstants.BANK_LOGO_BOC;
    	}else if(bankName.indexOf("建行")!=-1 || bankName.indexOf("建设银行")!=-1){
    		result = BankConstants.BANK_LOGO_CCB;
    	}
    	
    	// 判断今天是否为节假日
        String bankCodes = banks;
        
        // 判断是否开通了权限
        if (StringUtils.isBlank(bankCodes)){
        	return null;
        }
        boolean icbcCross = false;
        boolean icbcSuper = false;
        for(String bankCode:bankCodes.split(",")){
        	//优先使用同行(工行同行也直接返回)，如果没有，查询是否包含工行
        	bankCode = StringUtils.isBlank(bankCode)?"":bankCode.trim();
        	if(result!=null&&bankCode.equals(result)){
        		if("BOC".equals(bankCode)){
        			if(autoSettleHelper.isPrivate(bcFlag)
        	    			&&(mainOrder.getMerTxnAmt().compareTo(new BigDecimal("1000000.00")) == 1)){
        				return null;
        			}
        		}
        		return result;
        	}else if(bankCode.equals(SettlementExchangeConstants.STLM_EX_ICBC_CROSS)){
        		icbcCross = true;
        	}else if(bankCode.equals(SettlementExchangeConstants.STLM_EX_ICBC_SUPER)){
        		icbcSuper = true;
        	}
        }
        
        //如果开通了工行
        if(icbcCross){
        	if(!autoSettleHelper.isPrivate(bcFlag) && useCross(mainOrder, bankName, bcFlag, cardNum)){
        		// 对公转账走工行大额
    			return BankConstants.BANK_LOGO_ICBC;
        	}else if(autoSettleHelper.isPrivate(bcFlag) && !autoSettleHelper.isPettyAmt(mainOrder.getMerTxnAmt()) && useCross(mainOrder, bankName, bcFlag, cardNum)){
        		// 对私大于5W的走大额
    			return BankConstants.BANK_LOGO_ICBC;
        	}else if(StringUtils.equals(splitFlag, BatchPayConstants.SPLIT_FLAG_YES) && useCross(mainOrder, bankName, bcFlag, cardNum)) {
        		// 对私小于等于5W并且拆单的走大额
    			return BankConstants.BANK_LOGO_ICBC;
    		}
        }
        if(icbcSuper){
        	if(autoSettleHelper.isPrivate(bcFlag) && autoSettleHelper.isPettyAmt(mainOrder.getMerTxnAmt())
        			&&!StringUtils.equals(splitFlag, BatchPayConstants.SPLIT_FLAG_YES) && useSuper(mainOrder, bankName, bcFlag, cardNum)){
        		// 对私小于等于5万并且非拆单走工行超级网银
        		return BankConstants.BANK_LOGO_ICBC;
        	}
        }
    	
    	return null;
    }
    
    //企业默认规则，按工作日/节假日查询可用自动结算银行
    public String queryPayBankCode(CpsGenMainOrder mainOrder,String bankName,String bcFlag,String cardNum, String custId, String acctId,String splitFlag){
    	String banks = null;
    	String mainAcct=null;
    	
    	custId=cloudCustAcctRelDao.getCloudCustId(mainOrder);
    	// 当前时间
        Date curDate = new Date();
    	if (autoSettleHelper.isHoliday(curDate)) {
    		mainAcct=cloudCustAcctRelDao.getCloudAcct(mainOrder);//支持云账户自动结算
        	//节假日自动结算新规则
//        	custId = StringUtils.isBlank(custId)?mainOrder.getPayCustId():custId;
//        	bankCodes = queryHolidayBankCodes(custId, curDate);
//        	banks = queryHolidayBankCodes(StringUtils.isBlank(acctId)?mainOrder.getPayAcct():acctId, mainOrder.getGopayIntTxnCd());//支持云账户注释掉
        	banks = queryHolidayBankCodes(StringUtils.isBlank(acctId)?mainAcct:acctId, mainOrder.getGopayIntTxnCd());
        }else{
//        	banks = queryWorkDayBankCodes(StringUtils.isBlank(acctId)?mainOrder.getPayAcct():acctId, mainOrder.getGopayIntTxnCd());//支持云账户注释掉
        	mainAcct=cloudCustAcctRelDao.getCloudAcct(mainOrder);//支持云账户自动结算
        	banks = queryWorkDayBankCodes(StringUtils.isBlank(acctId)?mainAcct:acctId, mainOrder.getGopayIntTxnCd());
        }
    	return queryPayBankCode(mainOrder, bankName, bcFlag, cardNum, custId, acctId, banks,splitFlag);
    }
    
    //企业规则，按节假日查询可用自动结算银行
    public String queryHolidayPayBankCode(CpsGenMainOrder mainOrder,String bankName,String bcFlag,String cardNum, String custId, String acctId,String splitFlag){
    	
    	String mainAcct=cloudCustAcctRelDao.getCloudAcct(mainOrder);//支持云账户自动结算
    	custId=cloudCustAcctRelDao.getCloudCustId(mainOrder);
    	if(isPersonAcct(mainAcct)){
    		return queryPersonPayBankCode(mainOrder, bankName,
    				bcFlag, cardNum,
					custId, mainAcct, splitFlag,false);
    	}
//    	String banks = queryHolidayBankCodes(StringUtils.isBlank(acctId)?mainOrder.getPayAcct():acctId, mainOrder.getGopayIntTxnCd());//支持云账户自动结算 注释掉
    	String banks = queryHolidayBankCodes(StringUtils.isBlank(acctId)?mainAcct:acctId, mainOrder.getGopayIntTxnCd());
    	if(StringUtils.isBlank(banks)){
    		return null;
    	}
    	return queryPayBankCode(mainOrder, bankName, bcFlag, cardNum, custId, acctId, banks,splitFlag);
    }
    
    
    public String queryPersonPayBankCode(CpsGenMainOrder main,
    		CpsGenPayOrder pay,Date curDate){
    	
    	String mainAcct=cloudCustAcctRelDao.getCloudAcct(main);//支持云账户自动结算
    	String custId=cloudCustAcctRelDao.getCloudCustId(main);
		if (autoSettleHelper.isHoliday(curDate)) {
			return queryPersonPayBankCode(main, pay.getRecvBankName(),
					pay.getBcFlag(), pay.getRecvBankAcctNum(),
					custId, mainAcct, pay.getSplitFlag(),false);
		} else {
			return queryPersonPayBankCode(main, pay.getRecvBankName(),
					pay.getBcFlag(), pay.getRecvBankAcctNum(),
					custId, mainAcct, pay.getSplitFlag(),true);
		}
    	
    }
    
    
    /**
     * 个人用户查询自动结算方案是否开通
     * @param mainOrder
     * @param bankName
     * @param bcFlag
     * @param cardNum
     * @param custId
     * @param acctId
     * @param isWorkDay
     * @return
     */
	public String queryPersonPayBankCode(CpsGenMainOrder mainOrder,
			String bankName, String bcFlag, String cardNum, String custId,
			String acctId,String splitFlag,boolean isWorkDay) {
		
		String banks=null;
		//判断是否开通自动结算个性化方案   如果个性化过不再走通用方案
		if(isIndividualizationAutoSettle(acctId)){
			banks = queryPersonPayBankCode(
					StringUtils.isBlank(acctId) ? mainOrder.getPayAcct() : acctId,
					mainOrder.getGopayIntTxnCd(),isWorkDay);
		}else{
			//根据账户查询产品线code
			String procCode=queryPersonProcCode(acctId,custId);
			if(StringUtils.isBlank(procCode)){
				return null;
			}
			banks=queryPersonPayBankCode(procCode,
					mainOrder.getGopayIntTxnCd(),isWorkDay);
		}
		
		if(StringUtils.isBlank(banks)){
			return null;
		}
		
		return queryPayBankCode(mainOrder, bankName, bcFlag, cardNum, custId,
				acctId, banks,splitFlag);
		
		/*//个人首先获取个性化方案
		String banks = queryPersonPayBankCode(
				StringUtils.isBlank(acctId) ? mainOrder.getPayAcct() : acctId,
				mainOrder.getGopayIntTxnCd(),isWorkDay);
		//如果个性化没有银行，从通用获取
		if (StringUtils.isBlank(banks)) {
			//根据账户查询产品线code
			String procCode=queryPersonProcCode(acctId,custId);
			if(StringUtils.isBlank(procCode)){
				return null;
			}
			banks=queryPersonPayBankCode(procCode,
					mainOrder.getGopayIntTxnCd(),isWorkDay);
			if(StringUtils.isBlank(banks)){
				return null;
			}
		}
		
		return queryPayBankCode(mainOrder, bankName, bcFlag, cardNum, custId,
				acctId, banks);*/
	}
    
    
    
    private String queryPersonProcCode(String acctId, String custId) {
    	
    	StringBuilder sql = new StringBuilder();
    	sql.append("select t.prod_code, t.acct_id ");
    	sql.append("  from acps_acct_mast t    ");
    	sql.append(" where t.acct_id = :acctId ");//根据acctId可以唯一确定
    	//sql.append("   and t.cust_id = :custId ");

    	Map<String, Object> map = new HashMap<String, Object>();
		map.put("acctId", acctId);
		//map.put("custId", custId);
		
		List<Object[]> rsList = commonQueryDAO.findBySql(sql.toString(), map);
		if (rsList != null && rsList.size() > 0 ) {
			return (String) rsList.get(0)[0];
		}
		return null;
	}

	private String queryPersonPayBankCode(String string, String gopayIntTxnCd,boolean isWorkDay) {
    	
		StringBuilder sb = new StringBuilder();
		sb.append(" select t.gopay_int_txn_cd, t.acct_id, TO_CHAR(WMSYS.WM_CONCAT(t.bank_code)) bank_code ");
		sb.append(" from SS_TRANS_SETTLE_DTL t");
		sb.append(" where t.gopay_int_txn_cd = :intTxnCd ");
		sb.append("  and t.acct_id = :acctId ");
		sb.append("  and t.is_work_day =:isWorkDay");
		sb.append(" group by t.gopay_int_txn_cd,t.acct_id ");
		Map<String, Object> map = new HashMap<String, Object>();
		map.put("intTxnCd", gopayIntTxnCd);
		map.put("acctId", string);
		map.put("isWorkDay", isWorkDay ? WorkDayEnum.WorkDay.key
				: WorkDayEnum.Holiday.key);
		List<Object[]> rsList = commonQueryDAO.findBySql(sb.toString(), map);
		if (rsList != null && rsList.size() > 0 && rsList.get(0).length == 3) {
			//add by tianxin 2018年2月5日
			//若银行对应的自动结算状态为“关闭”，则在汇路选择时，不能选取该银行作为付款汇路。
            String banks = filterBankCodes((String) rsList.get(0)[2]);
			return banks;
		}
		return null;
	}

	private boolean useSuper(CpsGenMainOrder mainOrder,String bankName,String bcFlag,String cardNum){
    	if(autoSettleHelper.isBankAcross()){
			logger.info("orderId:" + mainOrder.getGopayOrderId()
					+ ",isPrivate:" + autoSettleHelper.isPrivate(bcFlag)
					+ ",existCorrespondBank:"
					+ autoSettleHelper.existCorrespondBank(bankName, cardNum));
			if(autoSettleHelper.existCorrespondBank(bankName, cardNum)){
		    	logger.error("gopayOrderId_" + mainOrder.getGopayOrderId()+" bankName is ICBC(super or cross)");
		    	return true;
			}
    	}
    	return false;
    }
	
	private boolean useCross(CpsGenMainOrder mainOrder,String bankName,String bcFlag,String cardNum){
    	if(autoSettleHelper.isBankAcross()){
			logger.info("orderId:" + mainOrder.getGopayOrderId()
					+ ",isPrivate:" + autoSettleHelper.isPrivate(bcFlag)
					+ ",existCorrespondBankCross:"
					+ autoSettleHelper.existCorrespondBankCross(bankName, cardNum));
			if(autoSettleHelper.existCorrespondBankCross(bankName, cardNum)){
		    	logger.error("gopayOrderId_" + mainOrder.getGopayOrderId()+" bankName is ICBC(super or cross)");
		    	return true;
			}
    	}
    	return false;
    }
    
    private String queryWorkDayBankCodes(String acctId, String intTxnCd){
    	StringBuilder sb = new StringBuilder();
    	sb.append(" select t.gopay_int_txn_cd, t.acct_id, TO_CHAR(WMSYS.WM_CONCAT(t.bank_code)) bank_code ");
    	sb.append(" from SS_TRANS_SETTLE_DTL t");
    	sb.append(" where t.gopay_int_txn_cd = :intTxnCd ");
    	sb.append("  and t.acct_id = :acctId ");
    	sb.append("  and t.is_work_day = "+ WorkDayEnum.WorkDay.key +" ");
    	sb.append(" group by t.gopay_int_txn_cd,t.acct_id ");
    	Map<String, Object> map = new HashMap<String, Object>();
        map.put("intTxnCd", intTxnCd);
        map.put("acctId", acctId);
        this.logger.error("acctId="+acctId+",intTxnCd=" + intTxnCd +sb.toString());
        List<Object[]> rsList = commonQueryDAO.findBySql(sb.toString(), map);
        if(rsList != null && rsList.size() > 0 && rsList.get(0).length==3){
            //add by tianxin 2018年2月5日
            //若银行对应的自动结算状态为“关闭”，则在汇路选择时，不能选取该银行作为付款汇路。
            String banks = filterBankCodes((String) rsList.get(0)[2]);
        	return banks;
        }
    	return null;
    }
    
    private String queryHolidayBankCodes(String acctId, String intTxnCd){
//    	StringBuilder sb = new StringBuilder();
//    	sb.append(" select t.RULE_ID,t.CUST_ID,t.PAY_BANK_CODES ");
//    	sb.append(" from AS_CUST_RULE t ");
//    	sb.append(" where 1=1 ");
//    	sb.append(" and t.IS_DEL = '0' ");
//    	sb.append(" and t.SETTLE_TIME_BEGIN<=to_timestamp(:curDate, 'yyyymmddHH24miss') ");
//        sb.append(" and t.SETTLE_TIME_END>=to_timestamp(:curDate, 'yyyymmddHH24miss') ");
//        sb.append(" and t.CUST_ID = :custId ");
//        Map<String, Object> map = new HashMap<String, Object>();
//        map.put("curDate", DateUtils.format(curDate, "yyyyMMddHHmmss"));
//        map.put("custId", custId);
//
//        List<Object[]> rsList = commonQueryDAO.findBySql(sb.toString(), map);
//        if(rsList != null && rsList.size() > 0){
//        	return (String)rsList.get(0)[2];
//        }
//    	return null;
    	//节假日自动结算新规则
    	StringBuilder sb = new StringBuilder();
    	sb.append(" select t.gopay_int_txn_cd, t.acct_id, TO_CHAR(WMSYS.WM_CONCAT(t.bank_code)) bank_code ");
    	sb.append(" from SS_TRANS_SETTLE_DTL t");
    	sb.append(" where t.gopay_int_txn_cd = :intTxnCd ");
    	sb.append("  and t.acct_id = :acctId ");
    	sb.append("  and t.is_work_day = "+ WorkDayEnum.Holiday.key +" ");
    	sb.append(" group by t.gopay_int_txn_cd,t.acct_id ");
    	Map<String, Object> map = new HashMap<String, Object>();
        map.put("intTxnCd", intTxnCd);
        map.put("acctId", acctId);
        List<Object[]> rsList = commonQueryDAO.findBySql(sb.toString(), map);
        if(rsList != null && rsList.size() > 0 && rsList.get(0).length==3){
            //add by tianxin 2018年2月5日
            //若银行对应的自动结算状态为“关闭”，则在汇路选择时，不能选取该银行作为付款汇路。
            String banks = filterBankCodes((String) rsList.get(0)[2]);
        	return banks;
        }
    	return null;
    }
    /**
     * 判断是否个性化过自动结算方案
     */
	public boolean isIndividualizationAutoSettle(String acctId) {
		
		StringBuilder sql = new StringBuilder();
		sql.append("select t.acct_id, t.solution_id                ");
		sql.append("        from ss_acct_solution_rel t            ");
		sql.append("       where t.acct_id =:acctId                ");
		sql.append("         and t.solution_type =:solutionType   ");

		Map<String, Object> map = new HashMap<String, Object>();
		map.put("acctId", acctId);
		map.put("solutionType", "TSE");

		List<Object[]> ssRelAcct = commonQueryDAO
				.findBySql(sql.toString(), map);

		if (ssRelAcct != null && ssRelAcct.size() > 0) {
			return true;
		}
		return false;
	}

	private Boolean isPersonAcct(String acctId) {
		if (StringUtils.isNotBlank(acctId)&&StringUtils.equals("1", acctId.substring(9, 10))) {
			// 个人账户
			return true;
		}
		return false;
	}

    /**
     * 过滤掉AS_BANK_LIMIT_CONFIG 中自动结算状态关闭的BankCode
     * 若BankCode不在AS_BANK_LIMIT_CONFIG中则不处理，例如TBANK不做处理
     * @param bankCodes
     * @return
     */
	public String filterBankCodes(String bankCodes){
        if (bankCodes != null) {
            Map<String, String> map = getAutoSettleBanks();

            List<String> tempList = Arrays.asList(bankCodes.split(","));

            //将Arrays.ArrayList类型转为ArrayList
            List<String> bankList = new ArrayList<>(tempList);

            for (Map.Entry<String,String> k : map.entrySet()) {
                if (bankList.contains(k.getKey()) && "0".equals(k.getValue())) {
                    bankList.remove(k.getKey());
                }
            }

            return StringUtils.join(bankList, ",");
        } else {
            return bankCodes;
        }

    }

    /**
     * 获取AS_BANK_LIMIT_CONFIG 表中银行代码与其自动结算开关状态
     * @return map(BANK_CODE,SETTLE_STATUS)
     */
    private Map<String,String> getAutoSettleBanks(){
        HashMap<String, String> map = new HashMap<>();

        StringBuilder sb = new StringBuilder();
        sb.append(" SELECT conf.BANK_CODE, conf.SETTLE_STATUS ");
        sb.append(" FROM AS_BANK_LIMIT_CONFIG conf ");
        sb.append(" where 1 = 1 ");

        List<Object[]> rsList = commonQueryDAO.findBySql(sb.toString());

        if (rsList != null && rsList.size() > 0) {
            for (Object[] x: rsList) {
                //map(BANK_CODE,SETTLE_STATUS)
                map.put(StringTools.checkNulltoString(x[0]),StringTools.checkNulltoString(x[1]));
            }
        }
        return map;
    }
}
